package com.ruoyi.common.core.redis;

import java.util.*;
import java.util.concurrent.TimeUnit;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.stereotype.Component;

/**
 * spring redis 工具类
 *
 * @author ruoyi
 **/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache
{
    public static final String DEFAULT_CACHE = "default_kv";
    @Autowired
    private EhCacheCacheManager cacheManager;

    /**
     * 缓存基本的对象，Integer、String、实体类等
     *
     * @param cacheName
     * @param key 缓存的键值
     * @param value 缓存的值
     */
    public <T> void setCacheObject(final String cacheName,final String key, final T value)
    {
        Cache cache = cacheManager.getCacheManager().getCache(cacheName);
        if(cache == null){
            return;
        }
        Element e = new Element(key, value);
        cache.put(e);
    }

    /**
     * 缓存基本的对象，Integer、String、实体类等
     *
     * @param key 缓存的键值
     * @param value 缓存的值
     */
    public <T> void setCacheObject(final String key, final T value)
    {
        setCacheObject(DEFAULT_CACHE, key, value);
    }

    /**
     * 缓存基本的对象，Integer、String、实体类等
     *
     * @param cacheName
     * @param key 缓存的键值
     * @param value 缓存的值
     * @param timeout 时间
     * @param timeUnit 时间颗粒度
     */
    public <T> void setCacheObject(final String cacheName, final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
    {
        Cache cache = cacheManager.getCacheManager().getCache(cacheName);
        if(cache == null){
            return;
        }
        Element e = new Element(key, value);
        int t = timeout;
        if(timeUnit.equals(TimeUnit.MINUTES)){
            t *= 60;
        }else if(timeUnit.equals(TimeUnit.HOURS)){
            t *= 60 * 60;
        }else if(timeUnit.equals(TimeUnit.DAYS)){
            t *= 60 * 60 * 24;
        }
        e.setTimeToLive(t);
        cache.put(e);
    }

    /**
     * 设置有效时间
     *
     * @param cacheName
     * @param key Redis键
     * @param timeout 超时时间
     * @return true=设置成功；false=设置失败
     */
    public boolean expire(final String cacheName, final String key, final long timeout)
    {
        return expire(cacheName, key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 设置有效时间
     *
     * @param cacheName
     * @param key Redis键
     * @param timeout 超时时间
     * @param timeUnit 时间单位
     * @return true=设置成功；false=设置失败
     */
    public boolean expire(final String cacheName, final String key, final long timeout, final TimeUnit timeUnit)
    {
        Cache cache = cacheManager.getCacheManager().getCache(cacheName);
        if(cache == null){
            return false;
        }
        Element e = cache.get(key);
        int t = (int)timeout;
        if(timeUnit.equals(TimeUnit.MINUTES)){
            t *= 60;
        }else if(timeUnit.equals(TimeUnit.HOURS)){
            t *= 60 * 60;
        }else if(timeUnit.equals(TimeUnit.DAYS)){
            t *= 60 * 60 * 24;
        }
        e.setTimeToLive(t);
        return true;
    }

    /**
     * 设置有效时间
     *
     * @param key Redis键
     * @param timeout 超时时间
     * @param timeUnit 时间单位
     * @return true=设置成功；false=设置失败
     */
    public boolean expire( final String key, final long timeout, final TimeUnit timeUnit)
    {
        return expire(DEFAULT_CACHE, key, timeout, timeUnit);
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> T getCacheObject(final String key)
    {
        return getCacheObject(DEFAULT_CACHE, key);
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param cacheName 缓存键值
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> T getCacheObject(final String cacheName, final String key)
    {
        Cache cache = cacheManager.getCacheManager().getCache(cacheName);
        if(cache == null){
            return null;
        }
        Element e = cache.get(key);
        if(e == null){
            return null;
        }else{
            return (T)e.getObjectValue();
        }
    }

    /**
     * 删除单个对象
     *
     * @param cacheName 缓存键值
     * @param key
     */
    public boolean deleteObject(final String cacheName, final String key)
    {
        Cache cache = cacheManager.getCacheManager().getCache(cacheName);
        if(cache == null){
            return false;
        }
        return cache.remove(key);
    }

    /**
     * 删除单个对象
     *
     * @param cacheName
     */
    public boolean deleteObject(final String cacheName)
    {
        Cache cache = cacheManager.getCacheManager().getCache(cacheName);
        if(cache == null){
            return false;
        }
        cache.removeAll();
        return true;
    }

    /**
     * 删除集合对象
     *
     * @param cacheName
     * @param collection 多个对象
     * @return
     */
    public boolean deleteObject(final String cacheName, final Collection collection)
    {
        Cache cache = cacheManager.getCacheManager().getCache(cacheName);
        if(cache == null){
            return false;
        }
        collection.forEach(e->{
            cache.remove(e.toString());
        });

        return true;
    }

    /**
     * 获得缓存的基本对象列表
     *
     * @param cacheName 缓存名称
     * @return 对象列表
     */
    public Collection<String> keys(final String cacheName)
    {
        Cache cache = cacheManager.getCacheManager().getCache(cacheName);
        if(cache == null){
            return Collections.emptyList();
        }
        return cache.getKeys();
    }

    /**
     * 清空全部缓存
     */
    public void clearAll(){
        cacheManager.getCacheManager().clearAll();
    }
}
